home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks '96 / MenuMadness / Source / C Source / DefaultMDEF.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-21  |  8.0 KB  |  372 lines  |  [TEXT/CWIE]

  1. #include <Icons.h>
  2. #include <QDOffscreen.h>
  3. #include "QDUtils.h"
  4. #include "MenuUtils.h"
  5. #include "MenuSelect.h"
  6. #include "DefaultMDEF.h"
  7.  
  8.  
  9.     
  10. static    short            itemCount;
  11.  
  12. static void ItemRect(short item, Rect *r, Rect* menuRect);
  13. static void DrawTheMenu(MenuHandle theMenu, Rect *menuRect, Point hitPt, short* inItem);
  14. static void DoMenuChoice(MenuHandle theMenu, Rect *menuRect, Point hitPt, short* inItem);
  15. static short IMAX(short a, short b);
  16. static void DrawMenuItem(MenuHandle theMenu, Rect *menuRect, short which, Boolean hilite);
  17. static void DrawMenuItemText(MenuHandle theMenu, Rect r, short which, Boolean hilite);
  18.  
  19.  
  20.  
  21. enum {kNoIconLeftMargin = 14};
  22.     
  23. typedef struct
  24.     {
  25.     short    font,size,lineHeight,leftMargin,rightMargin,cmdWidth,baseLine;
  26.     }MenuFontData, *MenuFontPtr, **MenuFontDataHandle;
  27.  
  28. static    MenuFontData    data;
  29.  
  30.     
  31. static void GetFontSettings()
  32. {
  33.     data.font = 0;
  34.     data.size = 0; 
  35.     
  36.     data.lineHeight =  18; 
  37.     data.leftMargin = 40;
  38.     data.rightMargin = 14; 
  39.     data.cmdWidth = 26; 
  40.     data.baseLine = 4;
  41. }
  42.     
  43. static void ItemRect(short item, Rect *r, Rect* menuRect)
  44. {
  45.     if ((item < 1) || (item > itemCount))
  46.         SetRect(r, 0, 0, 0, 0);
  47.     else
  48.         SetRect(r,     menuRect->left, menuRect->top + (data.lineHeight * (item-1)), 
  49.                     menuRect->right, menuRect->top + (data.lineHeight * (item)));                    
  50. }
  51.                 
  52.  
  53. static void DrawMenuItem(MenuHandle theMenu, Rect *menuRect, short which, Boolean hilite)
  54. {    
  55.     Rect    r;
  56.     
  57.     //SetRGBBackColor(52224,39168,26112);
  58.     
  59.     ItemRect(which, &r,menuRect);
  60.     if (hilite)
  61.         {
  62.         ForeColor(blackColor);
  63.         PaintRect(&r);
  64.         }
  65.     else
  66.         EraseMenuRect(&r);
  67.  
  68.     DrawMenuItemText(theMenu, r, which, hilite);
  69. }
  70.  
  71.  
  72.  
  73. static void DrawMenuItemText(MenuHandle theMenu, Rect r, short which, Boolean hilite)
  74. {
  75.     short        cmdChar, markChar;
  76.     Style        itemStyle;
  77.     RGBColor    back = {0,0,0}, grayColor = {0x7777,0x7777,0x7777};
  78.     Boolean        itemDisabled = !GetItemEnabled(theMenu, which);
  79.     GDHandle    gd = GetCurrentGD( *(Point*) &r );
  80.     Boolean     useGrayPat = false;//(((CGrafPtr)qd.thePort)->portPixMap[0]->pixelSize == 1);
  81.     Str255        itemStr;
  82.     short        iconID = 0;
  83.     Point        p;
  84.     CGrafPtr    savePort;
  85.     GDHandle    saveGD;
  86.     
  87.     GetGWorld(&savePort, &saveGD);
  88.     
  89.     back = savePort->rgbBkColor;    
  90.     
  91.     TextFont(data.font);
  92.     TextSize(data.size);
  93.     
  94.     GetItemIcon(theMenu, which, &iconID);
  95.     if (iconID)
  96.         {
  97.         SetPt(&p, r.left + 24, (r.top + r.bottom) >> 1);
  98.         PlotSmallMenuIcon(p, iconID + 256, itemDisabled ? ttDisabled : ttNone);
  99.         }
  100.     
  101.     /*if (itemDisabled )
  102.         TextMode(grayishTextOr);
  103.     else
  104.         TextMode(srcOr);*/
  105.         
  106.     GetItem(theMenu, which, itemStr);
  107.  
  108.     
  109.     if (itemStr[1] == '-' )
  110.         {
  111.         /*if (useGrayPat)
  112.             PenPat((ConstPatternParam)&qd.gray);
  113.         else*/
  114.             RGBForeColor(&grayColor);
  115.             
  116.         MoveTo(r.left, r.top  + (data.lineHeight >>1));
  117.         Line(r.right - r.left, 0);
  118.         }
  119.     else
  120.         {
  121.         if (hilite)
  122.             RGBForeColor(&back);
  123.         else
  124.             {
  125.             if (itemDisabled)
  126.                 RGBForeColor(&grayColor);
  127.             else
  128.                 ForeColor(blackColor);
  129.             }
  130.             
  131.         if (iconID)
  132.             MoveTo(r.left + data.leftMargin, r.bottom  - data.baseLine);
  133.         else
  134.             MoveTo(r.left + 16, r.bottom  - data.baseLine);
  135.         GetItemStyle(theMenu, which, &itemStyle);
  136.         TextFace(itemStyle);
  137.  
  138.         DrawString(itemStr);
  139.  
  140.         TextFace(0);
  141.         GetItemCmd(theMenu,which,&cmdChar);
  142.         GetItemMark(theMenu, which, &markChar);
  143.     
  144.     
  145.     // if it's a hier item, it has no mark or cmd to draw, just an arrow
  146.  
  147.         if (cmdChar == 0x1B) 
  148.             {
  149.             Point aLoc;
  150.             short y;
  151.             
  152.             if (itemDisabled )
  153.                 {
  154.                 /*if (useGrayPat)
  155.                     PenPat((ConstPatternParam)&qd.gray);
  156.                 else*/
  157.                     RGBForeColor(&grayColor);
  158.                 }
  159.  
  160.             SetPt(&aLoc, r.right - 7, r.top  +2);
  161.             for (y = 6 ; y >= 0 ; y -= 2 )
  162.                 {
  163.                 MoveTo(aLoc.h, aLoc.v);
  164.                 Line(0, y);
  165.                 aLoc.h = aLoc.h + 1;
  166.                 aLoc.v = aLoc.v + 1;
  167.                 }
  168.             }
  169.         else 
  170.             {
  171.             if ( markChar )     // if there's a mark & it's not a hier item 
  172.                 {
  173.                     TextFont(0);                                    // switch to chicago for tick symbol 
  174.                     MoveTo(r.left + 2, r.bottom - data.baseLine);
  175.                     DrawChar(markChar);
  176.                     TextFont(data.font);                                    // back to geneva 
  177.                 }
  178.             
  179.                 // ordinary item. draw mark and or cmd character  
  180.                 
  181.                 if (cmdChar )                 // draw cmd char 
  182.                     {
  183.                     char    str[2];
  184.                     str[1] =0;
  185.                     MoveTo(r.right - data.cmdWidth, r.bottom - data.baseLine);
  186.                     TextFont(0);                         //switch to Chicago for clover leaf symbol 
  187.                     str[0] = 0x11;
  188.                     DrawChar(0x11);
  189.                     TextFont(data.font);                // switch back to geneva
  190.                     str[0] = cmdChar;
  191.  
  192.                     DrawChar(cmdChar);                    // draw char itself 
  193.                     }
  194.                 
  195.                 }
  196.             }
  197.             
  198.     //PenPat(&qd.black);
  199. }
  200.                 
  201.                 
  202.  
  203.  
  204. static void DrawTheMenu(MenuHandle theMenu, Rect *menuRect, Point hitPt, short* inItem)
  205. {
  206.     short    x;
  207.     Rect    r;
  208.     
  209.     for (x = 1 ; x <= itemCount ; x++)
  210.         {
  211.         ItemRect(x, &r, menuRect);
  212.         DrawMenuItemText(theMenu, r, x, false);
  213.         }
  214.         
  215.     TextFont(0);
  216.     TextSize(12);
  217.     TextFace(0);
  218. }
  219.                             
  220.                             
  221. static void DoMenuChoice(MenuHandle theMenu, Rect *menuRect, Point hitPt, short* whichItem)
  222. {
  223.     short    inItem;
  224.     short     cmdChar;        
  225.         
  226.     if (PtInRect(hitPt , menuRect) )
  227.         inItem = ((hitPt.v - menuRect->top) / data.lineHeight) + 1;
  228.     else
  229.         inItem = 0;
  230.                 
  231.     if (HMGetBalloons())    
  232.         {
  233.         Rect    r;
  234.         
  235.         ItemRect(inItem, &r, menuRect);
  236.         ShowMenuBalloon(theMenu, *whichItem, inItem, &r);                    
  237.         }
  238.                 
  239.     // if it's in a disabled item then ignore it
  240.     if (!GetItemEnabled(theMenu, inItem))
  241.         inItem = 0;
  242.             
  243.     if (inItem == *whichItem)
  244.         return;
  245.                 
  246.     if (*whichItem) // unhilite last selected item
  247.         {
  248.             GetItemCmd(theMenu, *whichItem, &cmdChar);
  249.             if (cmdChar == 0x1B)    // last selected item was hierarchichal, so need to redraw 
  250.                 DrawTheMenu(theMenu,menuRect,hitPt, whichItem);
  251.             else                    // just unhilite last one 
  252.                 {
  253.                 DrawMenuItem(theMenu, menuRect, *whichItem, false);
  254.                 }
  255.         }
  256.                 
  257.     if (inItem) // hilite the new selected item
  258.         {
  259.         DrawMenuItem(theMenu, menuRect, inItem, true);
  260.         }
  261.         
  262.     TextFont(0);
  263.     TextSize(12);
  264.     TextFace(0);
  265.                 
  266.     *whichItem = inItem;
  267. }
  268.         
  269.  
  270. static short IMAX(short a, short b)
  271. {
  272.     return (a > b) ? a : b;
  273. }
  274.         
  275. static void CalculateMenuSize(MenuHandle theMenu, Rect *menuRect, Point hitPt, short* inItem)
  276. {
  277.     short    h, v, longest, x, txtWidth;
  278.     Str255    itemStr;
  279.     short     tempChar;
  280.     Boolean hasIcon = false;
  281.  
  282.     TextFont(data.font);
  283.     TextSize(data.size);
  284.     longest = 0;
  285.     for (x = 1 ; x <= itemCount ; x++)
  286.         {
  287.         short iconID = 0;
  288.  
  289.         GetItem(theMenu, x, itemStr);
  290.         txtWidth = StringWidth(itemStr);
  291.         GetItemCmd(theMenu, x, &tempChar);
  292.         if (tempChar )
  293.             txtWidth = txtWidth + data.cmdWidth;
  294.         longest = IMAX(txtWidth, longest);
  295.         if ((x <= 31) && (itemStr[1] == '-') )            // if item is a dash, make sure it is disabled
  296.             theMenu[0]->enableFlags &=     ~(1L << x);
  297.             
  298.         GetItemIcon(theMenu, x, &iconID);
  299.         if (iconID)
  300.             hasIcon = true;
  301.         }
  302.     
  303.     if (hasIcon)
  304.         h = longest + data.leftMargin + data.rightMargin;
  305.     else
  306.         h = longest + kNoIconLeftMargin + data.rightMargin;
  307.     v = itemCount * data.lineHeight;
  308.     theMenu[0]->menuWidth = h;
  309.     theMenu[0]->menuHeight = v;
  310.     TextFont(0);
  311.     TextSize(12);
  312. }
  313.                                                         
  314.                             
  315. static void CalculatePopupMenuRect(    MenuHandle theMenu, Rect *menuRect, 
  316.                                     Point hitPt, short* whichItem)
  317. {
  318.     Rect        r, screen;
  319.     GDHandle    gD;
  320.     Point        loc;
  321.  
  322.  
  323.     loc.h = hitPt.v;         // hitPt is upside down!! The h and the v are swapped.
  324.     loc.v = hitPt.h;
  325.     SetRect(&r, 0, 0, theMenu[0]->menuWidth, theMenu[0]->menuHeight);
  326.     OffsetRect(&r,  loc.h,  loc.v - (data.lineHeight * (*whichItem -1)));
  327.  
  328.     if (! (gD = GetCurrentGD(loc)))
  329.         gD = GetMainDevice();
  330.  
  331.     screen = gD[0]->gdRect;
  332.     InsetRect(&screen, 4, 4);
  333.     if (gD == GetMainDevice() )
  334.         screen.top += 20;
  335.  
  336.     if (r.top < screen.top )
  337.         OffsetRect(&r, 0, screen.top - r.top);
  338.     if (r.bottom > screen.bottom )
  339.         OffsetRect(&r, 0, screen.bottom - r.bottom);
  340.     if (r.right > screen.right )
  341.         OffsetRect(&r, screen.right - r.right, 0);
  342.     if (r.left < screen.left )
  343.         OffsetRect(&r, screen.left - r.left, 0);
  344.     
  345.     *menuRect = r;
  346.     *whichItem = r.top;
  347. }
  348.     
  349.         
  350. pascal void DefaultMDEF(    short msg, MenuHandle m, Rect *mRect,
  351.                             Point p, short* i)
  352. {    
  353.     itemCount = CountMItems(m);
  354.     GetFontSettings();
  355.             
  356.     switch (msg)
  357.         {
  358.         case mDrawMsg:
  359.             DrawTheMenu(m, mRect,p,i);
  360.             break;
  361.         case mChooseMsg:
  362.             DoMenuChoice(m, mRect,p,i);
  363.             break;
  364.         case mSizeMsg:
  365.             CalculateMenuSize(m, mRect,p,i);
  366.             break;
  367.         case mPopUpMsg:
  368.             CalculatePopupMenuRect(m, mRect,p,i);
  369.             break;
  370.         }
  371.         
  372. }